package com.kangfawei.io;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class FileSplit {
    // 源文件
    private File src;
    // 文件目的文件夹
    private String targetDir;
    // 分割后的文件名
    private List<String> targets;
    //分割的每块大小
    private int blockSize;
    // 分割后的数量
    private int size;
    // 文件大小
//    private long length;

    public FileSplit(String srcPath, String targetDir, int blockSize) {
        this.src = new File(srcPath);
        this.targetDir = targetDir;
        this.targets = new ArrayList<>();
        this.blockSize = blockSize;

        init();
    }

    public FileSplit(String srcPath, String targetDir) {
        this(srcPath,targetDir,1024);
    }

    // 初始化
    private void init(){
        // 总长度
        long length = this.src.length();
        // 块数
        this.size = (int)Math.ceil(length * 1.0 / blockSize);
        System.out.println(size);
        // 路径
        for (int i = 0; i < size; i++) {
            this.targets.add(this.targetDir + "/" + i + "-" + this.src.getName());
        }
    }


    /**
     * 分割文件
     * @throws IOException
     */
    public void splitFile() throws IOException {
        long length = src.length();
        // 初始位置以及实际每块大小
        int startPos = 0;
        int actualSize = (int)Math.min(length,this.blockSize);

        for (int i = 0; i < this.size; i++) {
            startPos = i * actualSize;
            // 最后一块
            if(i == this.size - 1){
                actualSize = (int)length;
            }else{
                actualSize = blockSize;
                length = length - actualSize;
            }
            System.out.println(i+"-->"+startPos+"-->"+actualSize);
            splitDetail(startPos,actualSize,i);
        }
    }

    /**
     * 将分割的文件写入目标文件夹中
     * @param startPos
     * @param actualSize
     * @param i
     * @throws IOException
     */
    private void splitDetail(int startPos,int actualSize,int i) throws IOException {
        RandomAccessFile raf1 =new RandomAccessFile(this.src,"r");
        RandomAccessFile raf2 =new RandomAccessFile(this.targets.get(i),"rw");
        raf1.seek(startPos);
        byte[] flush = new byte[1024];
        int len = 0;
        while ((len = raf1.read(flush)) != -1){
            if(actualSize > len){
                raf2.write(flush,0,len);
                actualSize -= len;
            }else{
                raf2.write(flush,0,actualSize);
            }
        }
        // 如果流不关闭，每次分割都会把剩下的全部写进去
        raf1.close();
        raf2.close();
    }

    /**
     * 文件合并
     * @param path
     * @throws IOException
     */
    public void mergeFile(String path) throws IOException {
        OutputStream os = new FileOutputStream(path,true);
        for (String target : this.targets) {
            InputStream is = new FileInputStream(target);
            byte[] flush = new byte[1024];
            int length = 0;
            while ((length = is.read(flush)) != -1) {
                os.write(flush,0,length);
            }
            is.close();
        }
        os.close();
    }

    /**
     * 文件合并2
     * 用SequenceInputStream操作
     * @param path
     * @throws IOException
     */
    public void mergeFile2(String path) throws IOException {
        OutputStream os = new FileOutputStream(path,true);
        Vector<InputStream> ins = new Vector<>();

        for (String target : this.targets) {
            ins.add(new FileInputStream(target));
        }

        SequenceInputStream sis = new SequenceInputStream(ins.elements());
        byte[] flush = new byte[1024];
        int length = 0;
        while ((length = sis.read(flush)) != -1) {
            os.write(flush,0,length);
        }
        sis.close();
        os.close();
    }
}
